/* -*- Mode: c; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/*
  RefObject (http://code.google.com/p/refobject/)
  Copyright (C) 2010-2011 MIURA Shirow (sharow)
*/

#include "RefAllocatorInternal.h"

typedef struct {
    RefAllocatorStdCMalloc mStdCMallocProc;
    RefAllocatorStdCFree mStdCFreeProc;
} RefAllocator;


static RefTypeObject *gAllocatorTypeObject = NULL;


RefTypeObject **
RefAllocator_GetTypeObject(void)
{
    return &gAllocatorTypeObject;
}

int
RefAllocator_IsValid(RefObject *aRefObject)
{
    return (RefObject_GetTypeObject(aRefObject) == &gAllocatorTypeObject);
}

static void
RefAllocator_Destructor(RefObject *aRefObject)
{
    ((RefAllocator *)RefObject_GetObject(aRefObject))->mStdCFreeProc(aRefObject);
}

RefObject *
RefAllocator_CreateFromStdCMallocFree(RefAllocatorStdCMalloc aStdCMalloc, RefAllocatorStdCFree aStdCFree)
{
    RefObject *refobj;
    RefAllocator *allocator;
    if (aStdCMalloc && aStdCFree) {
    } else {
        return NULL;
    }
    refobj = aStdCMalloc(RefObject_SizeOf() + sizeof(*allocator));
    allocator = RefObject_Construct(refobj, &gAllocatorTypeObject, RefAllocator_Destructor);
    allocator->mStdCMallocProc = aStdCMalloc;
    allocator->mStdCFreeProc = aStdCFree;
    return refobj;
}

void *
RefAllocator_Alloc(RefObject *aRefObject, unsigned int aSize)
{
    return ((RefAllocator *)RefObject_GetObject(aRefObject))->mStdCMallocProc(aSize);
}

void
RefAllocator_Free(RefObject *aRefObject, void *aPtr)
{
    ((RefAllocator *)RefObject_GetObject(aRefObject))->mStdCFreeProc(aPtr);
}

RefObject *
RefAllocatorForModule_CreateFromStdCMallocFree(RefAllocatorStdCMalloc aStdCMalloc, RefAllocatorStdCFree aStdCFree)
{
    return RefAllocator_CreateFromStdCMallocFree(aStdCMalloc, aStdCFree);
}
